package cj.primariaiquest.integration.endpoints;

import static cj.primariaiquest.model.Department.Alimentation;
import static cj.primariaiquest.model.Department.Fraud;
import static cj.primariaiquest.model.Department.ThievesProtection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.springframework.integration.annotation.MessageEndpoint;

import cj.primariaiquest.model.Department;
import cj.primariaiquest.model.Ticket;

/**
 * Message endpoint used to display all desks and their next numbers to be
 * processed.
 * 
 * @author parvu georgian
 * 
 */
@MessageEndpoint
public class MainScreenEndpoint {
    private static Logger logger = Logger.getLogger(MainScreenEndpoint.class);

    /**
     * <code>Map<Department, Map<String, Long>></code> used to store all
     * departments, and for each department to store all desks and their next
     * ticket numbers to be processed.
     */
    private static Map<Department, Map<String, Long>> desksAndNumbers;
    private static List<Ticket> canceledTickets;

    static {
	desksAndNumbers = new HashMap<Department, Map<String, Long>>();
	desksAndNumbers
		.put(Alimentation, new ConcurrentHashMap<String, Long>());
	desksAndNumbers.put(ThievesProtection,
		new ConcurrentHashMap<String, Long>());
	desksAndNumbers.put(Fraud, new ConcurrentHashMap<String, Long>());

	canceledTickets = Collections.synchronizedList(new ArrayList<Ticket>());
    }

    /**
     * Display all desks and the next tickets to be processed.
     * 
     * @param ticket
     *            Ticket representing the last processed ticket.
     */
    public void showNewTicketNumbers(final Ticket ticket) {
	logger.debug("MainScreenEndpoint - showNewTicketNumbers() - begin");

	updateMainScreen(ticket);

	for (Department dep : desksAndNumbers.keySet()) {
	    System.out.println(desksAndNumbers.get(dep));
	    logger.info(desksAndNumbers.get(dep));
	}
	logger.info("<=====================>");
	System.out.println("<=====================>");
	logger.debug("MainScreenEndpoint - showNewTicketNumbers() - end");
    }

    /**
     * Given the provided ticket updates the information that will be displayed
     * on the main screen
     * 
     * @param ticket
     *            last processed ticket.
     */
    private void updateMainScreen(final Ticket ticket) {
	// searched the next ticket that will be processed
	Ticket nextTicket = new Ticket(ticket.getDepartment(),
		ticket.getDesk(), ticket.getNumber() + 1);

	while (canceledTickets.contains(nextTicket)) {
	    nextTicket.setNumber(nextTicket.getNumber() + 1);
	}

	desksAndNumbers.get(nextTicket.getDepartment()).put(
		nextTicket.getDesk(), nextTicket.getNumber());
    }

    /**
     * Method used to receive and store canceled tickets.
     * 
     * @param ticket
     *            canceled ticket.
     */
    public void addCanceledTicket(final Ticket ticket) {
	canceledTickets.add(ticket);
    }

}
